大容量ファイルアップロードを冷静に対処する方法
Lukas Schneider
DevOps Engineer · Leapcell

大容量ファイルアップロードを冷静に対処する方法
大容量ファイルアップロードの最適化を検討する理由
フロントエンド開発では、画像、ビデオ、オーディオファイルなどのファイルアップロードが必要となるシナリオによく遭遇します。ファイルアップロード中に、ファイルが大きすぎる場合に問題が発生することがあります。
- アップロード時間が長くなり、ユーザーエクスペリエンスが低下する。
- 過剰なサーバー負荷とリソース消費を引き起こす。
- 不安定なネットワーク条件下でアップロードが失敗し、再アップロードが必要になり、時間と帯域幅を浪費する。
- ブラウザのメモリ使用量が多くなり、パフォーマンスと安定性に影響する。
これらの問題に対処するには、大容量ファイルアップロードを最適化する必要があります。
現代のインターネットアプリケーションでは、ユーザーはファイルアップロードに対してますます高い要求を持っています。
- ソーシャルプラットフォームで高解像度の画像やビデオを共有する。
- 教育プラットフォームで課題や教材を提出する。
- エンタープライズプラットフォームでプロジェクトドキュメントやレポートをアップロードする。
これらのシナリオでは、ユーザーがアップロードする必要のあるファイルは非常に大きく、数百メガバイトまたは数ギガバイトに達することもあります。従来の方法でファイルアップロードを行うと、前述の問題に直面します。
従来の方法では、ファイル全体を単一のリクエストボディとしてサーバーに送信します。このアプローチにはいくつかの欠点があります。
- 長いアップロード時間: ファイルサイズが大きいため、データの転送に時間がかかり、ユーザーはアップロード結果を見るために長時間待つ必要があります。
- 高いサーバー負荷: 大量のファイルは、サーバーが一度に大量のデータを受信して処理する必要があり、過剰なサーバーメモリ、CPU、帯域幅、その他のリソースを消費する可能性があります。
- 不安定なネットワークで失敗しやすい: 大容量ファイルの転送は、切断、タイムアウト、パケットロスなどのネットワークの問題の影響を受けやすく、アップロードが失敗し、ユーザーはファイル全体を再アップロードすることを余儀なくされます。
- 高いブラウザメモリ使用量: 大容量ファイルでは、ブラウザがファイル全体をメモリに読み込んで接続を維持する必要があるため、メモリ使用量が多くなり、他のページのパフォーマンスに影響を与える可能性があります。
これらの問題に対処するには、大容量ファイルアップロードの最適化が不可欠です。
設計アプローチ
大容量ファイルアップロードを最適化するための主なアプローチは次のとおりです。
1. チャンク分割
大きなファイルを小さなチャンクに分割し、各チャンクを個別のリクエストとしてサーバーに送信します。これにより、リクエストごとのデータ量が減り、アップロード時間が短縮され、サーバーの負荷が軽減され、再開可能なアップロードが可能になります。
function sliceFile(file, chunkSize) { const fileSize = file.size; const chunks = Math.ceil(fileSize / chunkSize); const slices = Array.from({ length: chunks }, (_, index) => { const start = index * chunkSize; const end = start + chunkSize; return file.slice(start, end); }); return slices; }
2. 並行処理
複数のチャンクリクエストをサーバーに同時に送信して、ネットワーク帯域幅とサーバーリソースを最大限に活用し、ユーザーエクスペリエンスを向上させます。
async function uploadChunks(fileChunks) { const uploadPromises = fileChunks.map((chunk) => fetch('/upload', { method: 'POST', body: chunk }) ); const responses = await Promise.all(uploadPromises); return responses; }
3. 圧縮
各チャンクをサーバーに送信する前に圧縮して、データサイズをさらに削減し、転送効率を向上させます。
async function compressChunk(chunk) { const compressedChunk = await new Promise((resolve, reject) => { const reader = new FileReader(); reader.onload = (event) => { const result = pako.deflate(event.target.result); resolve(result); }; reader.onerror = (event) => reject(event.error); reader.readAsArrayBuffer(chunk); }); return compressedChunk; }
4. 検証
各チャンクを送信する前または後に検証して、データの整合性と正確性を確保し、冗長または誤ったデータ転送を回避します。
async function verifyChunk(chunk) { const hash = await calculateHash(chunk); const response = await fetch(`/verify?hash=${hash}`); const result = await response.json(); return result; }
5. 再開可能なアップロード
ネットワーク障害が発生した場合、最初からやり直すのではなく、中断した時点からアップロードを続行し、時間を節約し、速度を向上させます。
async function resumeUpload(file, resumeByte) { const blob = file.slice(resumeByte); const formData = new FormData(); formData.append('file', blob); const response = await fetch('/upload', { method: 'POST', body: formData }); const result = await response.json(); return result; }
6. インスタントアップロード
ファイルをスライスしてアップロードする前に、そのハッシュを計算してサーバーに送信します。サーバーが同一のファイルを見つけた場合、すぐに成功応答を返すことができ、冗長なアップロードを回避できます。
async function checkFileExists(file) { const hash = await calculateHash(file); const response = await fetch(`/check?hash=${hash}`); const result = await response.json(); return result; }
まとめ
この記事では、大容量ファイルアップロードの最適化が必要な理由と、主な最適化戦略を紹介します。コード例を通じて、これらの最適化方法の実装方法を示し、読者が大容量ファイルアップロードの最適化のためのソリューションを理解し、適用できるようにすることを目的としています。
Leapcellは、バックエンドプロジェクトをホストするための最適な選択肢です。最大100 MBのファイルアップロードをサポートしています!
Leapcellは、Webホスティング、非同期タスク、およびRedis向けの次世代サーバーレスプラットフォームです。
多言語サポート
- Node.js、Python、Go、またはRustで開発。
無制限のプロジェクトを無料でデプロイ
- 使用量に対してのみ支払い — リクエストも請求もありません。
比類のない費用対効果
- アイドル料金なしの従量課金。
- 例:$25で、平均応答時間60msで694万リクエストをサポートします。
合理化された開発者エクスペリエンス
- 楽なセットアップのための直感的なUI。
- 完全に自動化されたCI/CDパイプラインとGitOps統合。
- 実行可能な洞察のためのリアルタイムメトリクスとロギング。
容易なスケーラビリティと高性能
- 高い並行性を容易に処理するための自動スケーリング。
- 運用上のオーバーヘッドはゼロ — 構築に集中するだけです。
ドキュメントで詳細をご覧ください!
Xでフォローしてください:@LeapcellHQ